/*
 * Copyright 2012 Faculty of Informatics - Masaryk University.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cz.muni.fi.pa165.creatures.web;

import cz.muni.fi.pa165.creatures.dto.WeaponDTO;
import cz.muni.fi.pa165.creatures.facades.EffectivityServiceFacade;
import cz.muni.fi.pa165.creatures.services.EffectivityService;
import cz.muni.fi.pa165.creatures.services.WeaponService;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.sourceforge.stripes.action.*;
import net.sourceforge.stripes.controller.LifecycleStage;
import net.sourceforge.stripes.integration.spring.SpringBean;
import net.sourceforge.stripes.security.action.Secure;
import net.sourceforge.stripes.validation.IntegerTypeConverter;
import net.sourceforge.stripes.validation.LocalizableError;
import net.sourceforge.stripes.validation.Validate;
import net.sourceforge.stripes.validation.ValidateNestedProperties;
import net.sourceforge.stripes.validation.ValidationErrors;
import net.sourceforge.stripes.validation.ValidationMethod;

/**
 *
 * @author xhajek11
 */
@Secure(roles = "admin")
@UrlBinding("/weapons/{$event}/{$weapon.id}")
public class WeaponsActionBean extends CreatureHuntingActionBean {

    final static Logger logger = Logger.getLogger(WeaponsActionBean.class.getName());

    @SpringBean
    protected WeaponService weaponService;

    @SpringBean
    protected EffectivityServiceFacade effectivityService;
    
    private List<String> selected;

    @ValidateNestedProperties(value = {
        @Validate(on = {"add", "save"}, field = "name", required = true),
        @Validate(on = {"add", "save"}, converter = IntegerTypeConverter.class,
            field = "ammunition", required = false, minvalue = 0),
        @Validate(on = {"add", "save"}, converter = IntegerTypeConverter.class,
            field = "range", required = false, minvalue = 0)
    })
    private WeaponDTO weapon;

    @DefaultHandler
    public Resolution all() {
        logger.log(Level.INFO, "listing all weapons");
        return new ForwardResolution("/weapons_show.jsp");
    }

    @Secure(roles = "admin")
    public Resolution create() {
        logger.log(Level.INFO, "creating new weapon");
        return new ForwardResolution("/weapons_create.jsp");
    }

    @Secure(roles = "admin")
    public Resolution add() {
        weaponService.create(weapon);
        logger.log(Level.INFO, "created new weapon {0}", weapon);
        return new RedirectResolution(this.getClass(), "all");
    }

    @Secure(roles = "admin")
    public Resolution delete() {
        effectivityService.removeWeaponWithEffectivities(weapon);
        logger.log(Level.INFO, "removed weapon {0}", weapon);
        return new RedirectResolution(this.getClass(), "all");
    }

    @Secure(roles = "admin")
    public Resolution deleteall() {
        List<WeaponDTO> weapons = weaponService.getAll();
        for (WeaponDTO weapon : weapons) {
            effectivityService.removeWeaponWithEffectivities(weapon);
        }
        logger.log(Level.INFO, "removed all weapons");
        return new RedirectResolution(this.getClass(), "all");
    }

    @Secure(roles = "admin")
    public Resolution deleteSelected() {
        if (selected != null) {
            for (String id : selected) {
                WeaponDTO selectedWeapon = weaponService.getById(Long.parseLong(id));
                if (selectedWeapon != null) {
                    effectivityService.removeWeaponWithEffectivities(selectedWeapon);
                }
            }
        }
        logger.log(Level.INFO, "removed weapons {0}", selected);
        return new RedirectResolution(this.getClass(), "all");
    }

    @DontValidate
    public Resolution cancel() {
        logger.log(Level.INFO, "cancel weapon");
        return new RedirectResolution(this.getClass(), "all");
    }

    @Before(stages = LifecycleStage.BindingAndValidation, on = {"edit", "save"})
    public void loadWeaponFromDatabase() {
        String ids = getContext().getRequest().getParameter("weapon.id");
        if (ids == null) {
            return;
        }
        weapon = weaponService.getById(Long.parseLong(ids));
    }

    @Secure(roles = "admin")
    public Resolution edit() {
        logger.log(Level.INFO, "editing weapon {0}", weapon);
        return new ForwardResolution("/weapons_edit.jsp");
    }

    @Secure(roles = "admin")
    public Resolution save() {
        weaponService.update(weapon);
        logger.log(Level.INFO, "edited weapon {0}", weapon);
        return new RedirectResolution(this.getClass(), "all");
    }

    public List<WeaponDTO> getWeapons() {
        return weaponService.getAll();
    }

    public WeaponDTO getWeapon() {
        return weapon;
    }

    public void setWeapon(WeaponDTO weapon) {
        this.weapon = weapon;
    }

    public Long getCount() {
        return weaponService.getCount();
    }

    public List<String> getSelected() {
        return selected;
    }

    public void setSelected(List<String> selected) {
        this.selected = selected;
    }

    public Resolution detail() {
        weapon = weaponService.getById(Long.parseLong(weapon.getId()));
        return new ForwardResolution("/weapons_detail.jsp");
    }

    @ValidationMethod(on = {"add"})
    public void validateUniqueAddWeaponName() {
        ValidationErrors errors = getContext().getValidationErrors();
        if (weaponService.getByName(weapon.getName()) != null) {
            errors.add("weapon.name", new LocalizableError("weapon.already_exists"));
        }
    }

    @ValidationMethod(on = {"save"})
    public void validateUniqueSaveRegionName() {
        ValidationErrors errors = getContext().getValidationErrors();
        WeaponDTO found = weaponService.getByName(weapon.getName());
        if (found != null && !found.getId().equals(weapon.getId())) {
            errors.add("weapon.name", new LocalizableError("weapon.already_exists"));
        }
    }
}
